home *** CD-ROM | disk | FTP | other *** search
- /*
- Gamepad & memory card emulation
- ===============================
-
- Written by LDChen
- */
-
- #include "fpse.h"
-
- #define ACKPAD sio->Delta |= DSR;
- #define NACKPAD
- // sio->Status &= ~DSR; sio->Delta |= DSR;
-
- #define B13 0x2000
- #define READ_CARD 0x80
-
- #define KPAD 1
- #define KMEM 2
-
- #ifdef MSB_FIRST
- #define L0 3
- #define L1 2
- #else
- #define L0 0
- #define L1 1
- #endif
-
- // This struct should be allocate in SIO_Type in the future...
- typedef struct {
- int Type;
- int Ptr;
- /* Gamepad fields */
- int PadEnd;
- void (*Joy_PollBack)(void);
- void (*Joy_Vibrate)(int);
- char Buf[16];
- /* Memory card fields */
- char MemBuf[256];
- union {
- UINT8 l[4];
- UINT32 hl;
- } Addr;
- int EndFlg,Crc;
- char *CardName;
- char MemoryCard[128*1024];
- } pad_type;
-
- static pad_type *flx=NULL;
- static pad_type pad[2];
- static int nflx=0;
- static char cd1[] = {"slot1"};
- static char cd2[] = {"slot2"};
- static char memcdpath[] = { "memcards\\" };
-
- static int MC_Event();
- static int MC_VSync();
-
- int PAD_Init(SIO_Type *sio)
- {
- int f,x;
- char buf[80];
-
- // Prepare the struct
- memset(pad,0,sizeof(pad));
-
- strcpy(buf,memcdpath);
- if (FPSEIni.Mcd1Name != NULL) strcat(buf,FPSEIni.Mcd1Name);
- else strcat(buf,cd1);
- pad[0].CardName = strdup(buf);
-
- strcpy(buf,memcdpath);
- if (FPSEIni.Mcd2Name != NULL) strcat(buf,FPSEIni.Mcd2Name);
- else strcat(buf,cd2);
- pad[1].CardName = strdup(buf);
-
- // GamePad header
- pad[0].Joy_PollBack = JOY0_Poll;
- pad[0].Joy_Vibrate = JOY0_Vibrate;
- pad[0].PadEnd = JOY0_InitHeader(pad[0].Buf);
- pad[1].Joy_PollBack = JOY1_Poll;
- pad[1].Joy_Vibrate = JOY1_Vibrate;
- pad[1].PadEnd = JOY1_InitHeader(pad[1].Buf);
-
- for (x=0;x<2;x++)
- {
- // Memory card header
- pad[x].MemBuf[2] = 0x5A;
- pad[x].MemBuf[3] = 0x5D;
-
- // Load memory card
- f = open(pad[x].CardName, O_RDONLY|O_BINARY);
- if (f!=-1)
- {
- read(f,pad[x].MemoryCard,128*1024);
- close(f);
- }
- }
-
- // Handlers
- EventCallBack[INT_SIO0] = MC_Event;
- VSyncCallBack[INT_SIO0] = MC_VSync;
-
- // Times to wait before irq
- sio->IrqSrc = SIO_IRQ_ASYNC;
- sio->IrqFlags = 0x00000003;
-
- return FPSE_OK;
- }
-
- void PAD_Close(SIO_Type *sio)
- {
- free(pad[0].CardName);
- free(pad[1].CardName);
- JOY0_Close();
- JOY1_Close();
- }
-
- void PAD_WriteData(SIO_Type *sio)
- {
- UINT8 *buf = sio->TxBuf;
- int v;
- UINT8 crc;
-
- if (flx == NULL) return;
-
- if (flx->Ptr == 0)
- {
- switch (*buf) {
- case 0x01:
- flx->Type = KPAD; flx->Ptr = 1;
- sio->IrqSrc = SIO_IRQ_ASYNC;
- sio->IrqFlags = 0x00000003;
- break;
- case 0x81:
- flx->Type = KMEM; flx->Ptr = 1;
- sio->IrqSrc = SIO_IRQ_VSYNC;
- if (compile)
- sio->IrqFlags = 0x00000001;
- else
- sio->IrqFlags = 0x00000002;
- break;
- default: break;
- }
- ACKPAD
- sio_async(sio,flx->Buf,1);
- NACKPAD
- return;
- }
-
- if (flx->Type == KPAD)
- {
- if (flx->Ptr == 1)
- {
- if ((*buf & 0x40) != 0x40)
- {
- ACKPAD
- sio_async(sio,flx->Buf,1);
- NACKPAD
- flx->Ptr = 0;
- return;
- }
- else flx->Joy_PollBack();
-
- } else flx->Joy_Vibrate(*buf);
- if (flx->Ptr < flx->PadEnd-1) ACKPAD
- sio_async(sio,flx->Buf + flx->Ptr,1);
- NACKPAD
- if (++flx->Ptr >= flx->PadEnd) flx->Ptr = 0;
- return;
- }
-
- if ((flx->Type & 0x7F) == KMEM)
- {
- if (flx->Ptr == 1)
- {
- switch (*buf) {
- case 'R':
- flx->Type |= READ_CARD;
- flx->EndFlg = 140;
- break;
- case 'W':
- flx->EndFlg = 138;
- break;
- default:
- flx->Ptr = 0;
- return;
- }
- }
- if (flx->Type & READ_CARD)
- {
- switch (flx->Ptr) {
- case 4:
- flx->Addr.l[L1] = *buf;
- flx->MemBuf[5] = *buf;
- flx->MemBuf[6] = 0x5C;
- flx->MemBuf[7] = 0x5D;
- flx->MemBuf[8] = *buf;
- break;
- case 5:
- flx->Addr.l[L0] = *buf;
- flx->MemBuf[9] = *buf;
- memcpy(flx->MemBuf+10,
- flx->MemoryCard+flx->Addr.hl*128,
- 128);
- crc = 0; // pad[flx].Addr.l[0] ^ pad[flx].Addr.l[1];
- for (v=8;v<128+10;v++)
- crc ^= flx->MemBuf[v];
- flx->MemBuf[v] = crc;
- flx->MemBuf[v+1] = 0x47;
- break;
- }
- }
- else {
- switch (flx->Ptr) {
- case 4:
- flx->Addr.l[L1] = *buf;
- flx->MemBuf[135] = 0x5C;
- flx->MemBuf[136] = 0x5D;
- flx->MemBuf[137] = 0x47;
- break;
- case 5:
- flx->Addr.l[L0] = *buf;
- flx->Crc = 0; // flx->Addr.l[0] ^ flx->Addr.l[1];
- break;
- case 134:
- printf("caculated crc=%02x\n",flx->Crc);
- if (*buf != flx->Crc)
- {
- flx->MemBuf[137] = 0x4E;
- break;
- }
- memcpy(flx->MemoryCard+flx->Addr.hl*128,
- flx->MemBuf+7,128);
- }
- if (flx->Ptr > 3 &&
- flx->Ptr < 134)
- {
- flx->MemBuf[flx->Ptr+1] = *buf;
- flx->Crc ^= *buf;
- }
- }
- if (flx->Ptr < flx->EndFlg) ACKPAD
- sio_async(sio,flx->MemBuf + flx->Ptr,1);
- NACKPAD
- if (++flx->Ptr >= flx->EndFlg) flx->Ptr = 0;
- // pad[flx].ptr = 0;
- // return;
- }
- }
-
- void PAD_UpdateStatus(SIO_Type *sio)
- {
- if (!(sio->Ctrl.Control16 & 2)) {
- pad[0].Ptr = pad[1].Ptr = 0;
- VSync_Register &= ~(1<<INT_SIO0);
- Event_Register &= ~(1<<INT_SIO0);
-
- flx = NULL;
- return;
- }
-
- if (sio->Ctrl.Control16 & B13) nflx = 1;
- else nflx = 0;
- flx = pad + nflx;
- }
-
- static int MC_Event()
- {
- VSync_Register &= ~(1<<INT_SIO0);
-
- return 1;
- }
-
- static int MC_VSync()
- {
- Event_Register &= ~(1<<INT_SIO0);
-
- return 1;
- }